package cn.xuqiudong.rpc.protocol.netty;

import cn.xuqiudong.rpc.common.constants.RequestType;
import cn.xuqiudong.rpc.common.constants.XqdConstants;
import cn.xuqiudong.rpc.common.model.Invoker;
import cn.xuqiudong.rpc.common.model.XqdRequest;
import cn.xuqiudong.rpc.common.model.XqdUrl;
import cn.xuqiudong.rpc.protocol.netty.handler.XqdClientInitializer;
import cn.xuqiudong.rpc.protocol.netty.model.NettyHeader;
import cn.xuqiudong.rpc.protocol.netty.model.NettyProtocolData;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 描述: netty客户端
 * @author Vic.xu
 * @date 2022-02-18 11:36
 */
public class XqdNettyClient {
    private static Logger logger = LoggerFactory.getLogger(XqdNettyClient.class);

    private Bootstrap bootstrap;

    private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup();

    public XqdNettyClient(){
        open();
    }

    public void open() {
        logger.info("XqdNettyClient open ");
        bootstrap = new Bootstrap();
        bootstrap.group(eventLoopGroup)
                .channel(NioSocketChannel.class)
                //.option(ChannelOption.AUTO_READ, true)
                .handler(new XqdClientInitializer());
    }

    /**
     * TODO  channel 的复用
     * @param invoker
     * @throws Exception
     */
    public void sendRequest(Invoker invoker) throws Exception {
        XqdUrl url = invoker.getXqdUrl();
        ChannelFuture future = bootstrap.connect(url.getAddress(), url.getPort()).sync();
        future.addListener(listener -> {
            if (future.isSuccess()) {
                logger.debug("connect rpc server  success");
            } else {
                logger.warn("connect rpc server   failed .");
                future.cause().printStackTrace();
                eventLoopGroup.shutdownGracefully();
            }
        });
        NettyProtocolData<XqdRequest> data = new NettyProtocolData<>();
        NettyHeader header = new NettyHeader(XqdConstants.MAGIC, RequestType.REQUEST.code(), invoker.getRequestId());
        data.setBody(invoker.getXqdRequest());
        data.setHeader(header);
        future.channel().writeAndFlush(data);
    }



}
